package com.qh.pay.service;

import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import com.qh.pay.api.utils.*;
import com.qh.redis.RedisConstants;
import org.apache.commons.lang3.StringUtils;

import com.alibaba.fastjson.JSONObject;
import com.qh.common.config.CfgKeyConst;
import com.qh.common.config.Constant;
import com.qh.common.utils.R;
import com.qh.pay.api.Order;
import com.qh.pay.api.PayConstants;
import com.qh.pay.api.constenum.AuditResult;
import com.qh.pay.api.constenum.OrderParamKey;
import com.qh.pay.api.constenum.PaymentMethod;
import com.qh.pay.domain.MerchCharge;
import com.qh.pay.domain.Merchant;
import com.qh.pay.domain.PayAuditDO;
import com.qh.pay.domain.RecordFoundAcctDO;
import com.qh.pay.domain.RecordMerchBalDO;
import com.qh.pay.domain.RecordPayMerchBalDO;
import com.qh.redis.service.RedisUtil;

/**
 * @version 1.0.0
 * @ClassName PayService
 * @Description 支付服务类
 * @Date 2017年11月6日 下午2:44:55
 */
public interface PayService {

    /**
     * @param merchant
     * @return
     * @Description 发起支付
     */
    Object order(Merchant merchant, JSONObject jo);
    /**
     * @param merchant
     * @return
     * @Description 发起支付
     */
    Object outChannal(Merchant merchant, JSONObject jo);

    /**
     * @param merchNo
     * @param orderNo
     * @param request
     * @param requestBody
     * @Description 支付后台回调
     */
    R notify(String merchNo, String orderNo, HttpServletRequest request, String requestBody);


    /**
     * @param merchNo
     * @param orderNo
     * @Description 订单回调后通知
     */
    String orderNotifyMsg(String merchNo, String orderNo);

    /**
     * @param merchNo
     * @param orderNo
     * @return
     * @Description 事件过期订单回调后通知
     */
    String eventOrderNotifyMsg(String merchNo, String orderNo);
    void orderNotifySync(Order order);



    /**
     * @param merchNo
     * @param orderNo
     * @Description 订单通知保存
     */
    void orderDataMsg(String merchNo, String orderNo);

    void orderDataMsg( String outChannel, String accountNo, String monAmount,
                      String msg,String businessNo);

    /**
     * @param merchant
     * @param jo
     * @return
     * @Description 支付订单查询
     */
    R query(Merchant merchant, JSONObject jo);
    /**
     * @return
     * @Description 支付订单查询
     */
    R query(String merchNo, String  orderNo);


    /**
     * @param merchant
     * @param jo
     * @return
     * @Description 代付受理
     */
    R orderAcp(Merchant merchant, JSONObject jo);


    /**
     * @param merchNo
     * @param orderNo
     * @Description 审核未通过
     */
    void orderAcpNopassDataMsg(String merchNo, String orderNo);

    /**
     * @param merchNo
     * @param orderNo
     * @Description 代付下单发起
     */
    R orderAcp(String merchNo, String orderNo);

    /**
     * @param merchNo
     * @param orderNo
     * @return
     * @Description 代付订单回调通知
     */
    String orderAcpNotifyMsg(String merchNo, String orderNo);

    /**
     * @param merchNo
     * @param orderNo
     * @return
     * @Description 事件过期订单回调后通知
     */
    String eventOrderAcpNotifyMsg(String merchNo, String orderNo);

    /**
     * @param merchNo
     * @param orderNo
     * @Description 代付最终保存结果
     */
    void orderAcpDataMsg(String merchNo, String orderNo);

    /**
     * @param merchNo
     * @param orderNo
     * @param request
     * @param requestBody
     * @return
     * @Description 代付回调通知
     */
    R notifyAcp(String merchNo, String orderNo, HttpServletRequest request, String requestBody);

    /**
     * @param merchant
     * @param jo
     * @return
     * @Description 代付查询
     */
    R acpQuery(Merchant merchant, JSONObject jo);


    /**
     * @param order
     * @return
     * @Description 前台返回地址
     */
    static String commonReturnUrl(Order order) {
        String domain = order.getCallbackDomain();
        if (StringUtils.isBlank(order.getCallbackDomain())) {
            domain = RedisUtil.getSysConfigValue(CfgKeyConst.pay_domain);
        }
        return domain + RedisUtil.getSysConfigValue(CfgKeyConst.pay_return_url) +
                order.getPayCompany() + "/" + order.getMerchNo() + "/" + order.getOrderNo();
    }

    /**
     * @param order
     * @return
     * @Description 后台返回地址
     */
    static String commonNotifyUrl(Order order) {
        String domain = order.getCallbackDomain();
        if (StringUtils.isBlank(order.getCallbackDomain())) {
            domain = RedisUtil.getSysConfigValue(CfgKeyConst.pay_domain);
        }
        return domain + RedisUtil.getSysConfigValue(CfgKeyConst.pay_notify_url) +
                order.getPayCompany() + "/" + order.getMerchNo() + "/" + order.getOrderNo();
    }

    /**
     * @param order
     * @return
     * @Description 前台返回地址
     */
    static String commonAcpReturnUrl(Order order) {
        String domain = order.getCallbackDomain();
        if (StringUtils.isBlank(order.getCallbackDomain())) {
            domain = RedisUtil.getSysConfigValue(CfgKeyConst.pay_domain);
        }
        return domain + RedisUtil.getSysConfigValue(CfgKeyConst.pay_acp_return_url) +
                order.getPayCompany() + "/" + order.getMerchNo() + "/" + order.getOrderNo();
    }

    /**
     * @param order
     * @return
     * @Description 后台返回地址
     */
    public static String commonAcpNotifyUrl(Order order) {
        String domain = order.getCallbackDomain();
        if (StringUtils.isBlank(order.getCallbackDomain())) {
            domain = RedisUtil.getSysConfigValue(CfgKeyConst.pay_domain);
        }
        return domain + RedisUtil.getSysConfigValue(CfgKeyConst.pay_acp_notify_url) +
                order.getPayCompany() + "/" + order.getMerchNo() + "/" + order.getOrderNo();
    }

    /**
     * @return
     * @throws Exception
     * @Description 跳转地址
     */
    static String commonJumpUrl(Order order) throws Exception {
        String domain = order.getCallbackDomain();
        if (StringUtils.isBlank(order.getCallbackDomain())) {
            domain = RedisUtil.getSysConfigValue(CfgKeyConst.pay_domain);
        }
        return domain + RedisUtil.getSysConfigValue(CfgKeyConst.pay_jump_url) +
                "?" + PayConstants.web_context + "=" + paramEncrypt(order.getMerchNo(), order.getOrderNo());
    }

    /**
     * @return
     * @throws Exception
     * @Description 快捷绑卡跳转地址
     */
    static String commonCardUrl(Order order) throws Exception {
        String domain = order.getCallbackDomain();
        if (StringUtils.isBlank(order.getCallbackDomain())) {
            domain = RedisUtil.getSysConfigValue(CfgKeyConst.pay_domain);
        }
        return domain + RedisUtil.getSysConfigValue(CfgKeyConst.pay_card_url) +
                "?" + PayConstants.web_context + "=" + paramEncrypt(order.getMerchNo(), order.getOrderNo());
    }

    /**
     * @param order
     * @return
     * @Description 支付扫码跳转地址
     */
    static String commonQrUrl(Order order) throws Exception {
//		String domain = order.getCallbackDomain();
//		if(StringUtils.isBlank(order.getCallbackDomain())) {
//		String	domain = RedisUtil.getSysConfigValue(CfgKeyConst.pay_domain);
//		}
        return RedisUtil.getSysConfigValue(CfgKeyConst.pay_domain) + RedisUtil.getSysConfigValue(CfgKeyConst.pay_qr_url) +
                "?" + PayConstants.web_context + "=" + paramEncrypt(order.getMerchNo(), order.getOrderNo());
    }

    static String paramEncrypt(String merchNo, String orderNo) throws Exception {
        return URLEncoder.encode(AesUtil.encrypt(merchNo + RedisConstants.link_symbol + orderNo,
				AesUtil.getPay_key()), Constant.ec_utf_8);
    }

    /**
     * @param order
     * @return
     * @Description 初始化返回数据
     */
    static Map<String, String> initRspData(Order order) {
        Map<String, String> data = new HashMap<>();
        data.put(OrderParamKey.merchNo.name(), order.getMerchNo());
        data.put(OrderParamKey.orderNo.name(), order.getOrderNo());
        data.put(OrderParamKey.outChannel.name(), order.getOutChannel());
        return data;
    }

    /**
     * @param order
     * @return
     * @Description 初始化商户资金流水
     */
    static RecordMerchBalDO initRdMerchBal(Order order, int feeType, int orderType, int profitLoss) {
        RecordMerchBalDO rdMerchBal = new RecordMerchBalDO();
        rdMerchBal.setOrderNo(order.getOrderNo());
        rdMerchBal.setMerchNo(order.getMerchNo());
        rdMerchBal.setFeeType(feeType);
        rdMerchBal.setOrderType(orderType);
        rdMerchBal.setCrtDate(order.getCrtDate());
        rdMerchBal.setProfitLoss(profitLoss);
        return rdMerchBal;
    }

    /**
     * @param merchCharge
     * @return
     * @Description 初始化商户资金流水
     */
    static RecordMerchBalDO initRdMerchChargeBal(MerchCharge merchCharge, int feeType, int orderType, int profitLoss) {
        RecordMerchBalDO rdMerchBal = new RecordMerchBalDO();
        rdMerchBal.setOrderNo(merchCharge.getBusinessNo());
        rdMerchBal.setMerchNo(merchCharge.getMerchNo());
        rdMerchBal.setFeeType(feeType);
        rdMerchBal.setOrderType(orderType);
        rdMerchBal.setCrtDate(merchCharge.getCrtDate());
        rdMerchBal.setProfitLoss(profitLoss);
        return rdMerchBal;
    }

    /**
     * @param order
     * @return
     * @Description 初始化平台资金流水
     */
    static RecordFoundAcctDO initRdFoundAcct(Order order, int feeType, int orderType, int profitLoss, String username) {
        RecordFoundAcctDO rdFoundAcct = new RecordFoundAcctDO();
        rdFoundAcct.setOrderNo(order.getOrderNo());
        rdFoundAcct.setMerchNo(order.getMerchNo());
        rdFoundAcct.setFeeType(feeType);
        rdFoundAcct.setOrderType(orderType);
        rdFoundAcct.setCrtDate(order.getCrtDate());
        rdFoundAcct.setProfitLoss(profitLoss);
        rdFoundAcct.setUsername(username);
        return rdFoundAcct;
    }

    /**
     * @param order
     * @return
     * @Description 初始化平台资金流水
     */
    static RecordFoundAcctDO initRdFoundAcct(Order order, int feeType, int orderType, int profitLoss) {
        return initRdFoundAcct(order, feeType, orderType, profitLoss, null);
    }

    /**
     * @param order
     * @return
     * @Description 初始化第三方支付公司资金流水
     */
    static RecordPayMerchBalDO initRdPayMerchAcct(Order order, int feeType, int orderType, int profitLoss) {
        RecordPayMerchBalDO rdPayMerchAcct = new RecordPayMerchBalDO();
        rdPayMerchAcct.setOrderNo(order.getOrderNo());
        rdPayMerchAcct.setMerchNo(order.getMerchNo());
        rdPayMerchAcct.setFeeType(feeType);
        rdPayMerchAcct.setOrderType(orderType);
        rdPayMerchAcct.setCrtDate(order.getCrtDate());
        rdPayMerchAcct.setProfitLoss(profitLoss);
        rdPayMerchAcct.setPayCompany(order.getPayCompany());
        rdPayMerchAcct.setOutChannel(order.getOutChannel());
        rdPayMerchAcct.setPayMerch(order.getPayMerch());
        return rdPayMerchAcct;
    }

    /**
     * @param order
     * @return
     * @Description 初始化审核记录
     */
    static PayAuditDO initPayAudit(Order order, int auditType) {
        PayAuditDO payAudit = new PayAuditDO();
        payAudit.setOrderNo(order.getOrderNo());
        payAudit.setMerchNo(order.getMerchNo());
        payAudit.setAuditType(auditType);
        payAudit.setAuditResult(AuditResult.init.id());
        payAudit.setCrtTime(DateUtil.getCurrentTimeInt());
        return payAudit;
    }

    /**
     * 支付商户号分身
     *
     * @param payMerch
     * @return
     */
    static String PayMerchAvatar(String payMerch) {
        if (payMerch.lastIndexOf("_" + PaymentMethod.D0) > 0) {
            payMerch = payMerch.substring(0, payMerch.lastIndexOf("_" + PaymentMethod.D0));
        } else if (payMerch.lastIndexOf("_" + PaymentMethod.D1) > 0) {
            payMerch = payMerch.substring(0, payMerch.lastIndexOf("_" + PaymentMethod.D1));
        } else if (payMerch.lastIndexOf("_" + PaymentMethod.T1) > 0) {
            payMerch = payMerch.substring(0, payMerch.lastIndexOf("_" + PaymentMethod.T1));
        } else if (payMerch.lastIndexOf("_" + PaymentMethod.T0) > 0) {
            payMerch = payMerch.substring(0, payMerch.lastIndexOf("_" + PaymentMethod.T0));
        }
        return payMerch;
    }

    /**
     * @param merchNo
     * @param orderNo
     * @Description 商户充值保存数据
     */
    void chargeDataMsg(String merchNo, String orderNo);

    /**
     * @param merchNo
     * @param orderNo
     * @param businessNo
     * @return
     * @Description 手动同步
     */
    R syncOrder(String merchNo, String orderNo, String businessNo);

    /**
     * @param merchNo
     * @param orderNo
     * @param businessNo
     * @return
     * @Description 同步代付订单信息
     */
    R syncOrderAcp(String merchNo, String orderNo, String businessNo);

    /**
     * @param order
     * @return
     * @Description 用户提现
     */
    R withdraw(Order order);

    /**
     * @param orderNo
     * @param merchNo
     * @param auditType
     * @return
     * @Description 线下转账
     */
    R offlineTransfer(String orderNo, String merchNo, Integer auditType);

}
